/**
 *
 */
package com.hexacta.hrs.domain.helper;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.lang.time.DateUtils;
import org.vectrics.common.util.DateUtil;
import org.vectrics.employee.Employee;

import com.hexacta.hrs.domain.employee.history.AssignabilityStatus;
import com.hexacta.hrs.domain.employee.history.CareerRole;
import com.hexacta.hrs.domain.staffing.assignment.AvailabilityStatus;
import com.hexacta.hrs.domain.staffing.assignment.EmployeeAssignment;
import com.hexacta.hrs.services.staffing.impl.EmployeeAssignmentDTO;
import com.hexacta.hrs.timeoff.TimeOff;

/**
 * @author ldeveikis
 * 
 */
public abstract class EmployeeAssignmentHelper {

//    public static List<EmployeeAssignmentDTO> createAssginmentsForHistoryRoles(final Employee employee,
//            final List<EmployeeAssignmentDTO> assignments) {
//        List<EmployeeAssignmentDTO> toReturn = new ArrayList<EmployeeAssignmentDTO>();
//        for (EmployeeAssignmentDTO assignment : assignments) {
//            toReturn.addAll(EmployeeAssignmentHelper.createAssginmentsForHistoryRoles(employee, assignment));
//        }
//        return toReturn;
//    }
//
//    public static List<EmployeeAssignmentDTO> createAssginmentsForHistoryRoles(final Employee employee,
//            final EmployeeAssignmentDTO assignment) {
//        List<EmployeeAssignmentDTO> toReturn = new ArrayList<EmployeeAssignmentDTO>();
//        List<CareerRole> roles = EmployeeHelper.findRolesBetweenDates(employee, assignment.getFrom().getTime(),
//                assignment.getTo().getTime());
//        if (roles.size() > 1 && !allEqualWithoutPercentage(roles)) {
//            // esto quiere decir que tiene mas de un role en el assignment
//            // dado. entonces debo crear distitos DTOs para cada role. Los
//            // paso a un treemap para tenerlos ordenados, por que solo tengo
//            // el date de inicio pero no el de fin
//            TreeMap<Date, CareerRole> ordenedRoles = new TreeMap<Date, CareerRole>();
//            for (CareerRole role : roles) {
//                ordenedRoles.put(role.getEffectiveDate(), role);
//            }
//            Iterator<Date> iterator = ordenedRoles.keySet().iterator();
//            Date effectiveFrom;
//            Date nextEffectiveFrom = iterator.next();
//            Date from;
//            Date to = nextEffectiveFrom;
//            // while (iterator.hasNext()) {
//            while (!DateUtils.isSameDay(nextEffectiveFrom, assignment.getTo().getTime())
//                    && !DateUtils.isSameDay(to, assignment.getTo().getTime())) {
//                effectiveFrom = nextEffectiveFrom;
//                if (assignment.getFrom().getTime().after(effectiveFrom)) {
//                    from = assignment.getFrom().getTime();
//                } else {
//                    from = effectiveFrom;
//                }
//
//                if (iterator.hasNext()) {
//                    while (iterator.hasNext() && to.before(from)) {
//                        nextEffectiveFrom = iterator.next();
//                        to = DateUtil.sumar(-1, nextEffectiveFrom);
//                    }
//                } else {
//                    to = assignment.getTo().getTime();
//                }
//                // to = nextEffectiveFrom;
//                toReturn.add(EmployeeAssignmentHelper.createDTO(assignment, from, to, ordenedRoles.get(effectiveFrom)
//                        .getCareerRole().getDescription()));
//            }
//        } else {
//            toReturn.add(assignment);
//        }
//        return toReturn;
//    }
//
//    /**
//     * @param roles
//     * @return
//     */
//    private static boolean allEqualWithoutPercentage(final List<CareerRole> roles) {
//
//        boolean res = true;
//
//        for (int i = 1; i < roles.size(); i++) {
//            res = res && roles.get(i).getCareerRole().equals(roles.get(i - 1).getCareerRole());
//        }
//        return res;
//    }

    public static EmployeeAssignmentDTO createDTO(final EmployeeAssignmentDTO assignment, final Date from,
            final Date to, final String role) {
        Calendar calFrom = Calendar.getInstance();
        calFrom.setTime(from);
        Calendar calTo = Calendar.getInstance();
        calTo.setTime(to);
        return EmployeeAssignmentHelper.createDTO(assignment.getEmployeeName(), assignment.getEmployeeID(), role,
                assignment.getAssignmentID(), calFrom, calTo, assignment.getPorcentage(), assignment.getFTE(),
                assignment.getAvailabilityStatus(), assignment.getProjectName());

    }

    /**
     * Instancia y devuelve un DTO {@link EmployeeAssignmentDTO} en la
     * informacion del empleado pasada como parametro
     * 
     * @param employee
     * @return
     */
    public static EmployeeAssignmentDTO createDTO(final String name, final Long idEmployee, final String role,
            final Long assigId, final Calendar from, final Calendar to, final double porc, final double FTE,
            final AvailabilityStatus status, final String projectName) {

        EmployeeAssignmentDTO dto = new EmployeeAssignmentDTO();
        dto.setEmployeeName(name);
        dto.setEmployeeID(idEmployee);
        dto.setAssignmentID(assigId);
        dto.setFrom(from);
        dto.setTo(to);
        dto.setRole(role);
        dto.setPorcentage(porc);
        dto.setFTE(FTE);
        dto.setAvailabilityStatus(status);
        dto.setProjectName(projectName);

        return dto;
    }

    /**
     * Devuelve las asignaciones para el empleado dado
     * 
     * @param employee
     * @param allEmployeeAssignments
     * @return
     */
    public static List<EmployeeAssignment> findAssignmentsForEmployee(final Employee employee,
            final Collection<EmployeeAssignment> allEmployeeAssignments) {
        List<EmployeeAssignment> list = new ArrayList<EmployeeAssignment>();
        Iterator<EmployeeAssignment> it = allEmployeeAssignments.iterator();

        while (it.hasNext()) {
            EmployeeAssignment assig = it.next();

            if (assig.getEmployee().equals(employee)) {
                list.add(assig);
                it.remove();
            }

        }

        return list;
    }

    /**
     * Instancia y devuelve un {@link EmployeeAssignmentDTO} basandose en la
     * informacion pasada como parametro
     * 
     * @param employee
     * @return
     */
    public static EmployeeAssignmentDTO createDTO(final Employee employee, final Date from, final Date to,
            final double d) {
        Calendar calFrom = Calendar.getInstance();
        if (employee.getDateStart().after(from)) {
            calFrom.setTime(employee.getDateStart());
        } else {
            calFrom.setTime(from);
        }
        Calendar calTo = Calendar.getInstance();
        if (employee.getDateEnd() != null && employee.getDateEnd().before(to)) {
            calTo.setTime(employee.getDateEnd());
        } else {
            calTo.setTime(to);
        }
        double fte = employee.getHoursPerDay() * d / 8;
        return EmployeeAssignmentHelper.createDTO(employee.getPerson().getName(), employee.getId(), employee
                .getFunction().getDescription(), null, calFrom, calTo, d, fte, EmployeeAssignmentHelper
                .getAvailabilityStatusFromNoAssignedEmployee(employee), null, " - ", null);
    }

    /**
     * Instancia y devuelve un {@link EmployeeAssignmentDTO} basandose en la
     * informacion del empleado pasada como parametro
     * 
     * @param employee
     * @return
     */
    public static List<EmployeeAssignmentDTO> createDTO(final Employee employee, final Date from, final Date to) {

        Set<AssignabilityStatus> status = employee.getEmploymentConditionHistory().getAssignabilityStatuses();
        List<EmployeeAssignmentDTO> toReturn = new ArrayList<EmployeeAssignmentDTO>();

        for (AssignabilityStatus st : status) {
            if ((st.getEndDate() == null || st.getEndDate().after(from)) && st.getEffectiveDate().before(to)
                    && st.isAvailable()) {
                Date endDate = st.getEndDate() == null ? to : st.getEndDate();
                toReturn.add(createSingleDTO(employee, st.getEffectiveDate(), endDate));
            }
        }
        return toReturn;
    }

    /**
     * @param employee
     * @param from
     * @param to
     * @return
     */
    private static EmployeeAssignmentDTO createSingleDTO(final Employee employee, final Date from, final Date to) {
        Calendar calFrom = Calendar.getInstance();
        if (employee.getDateStart().after(from)) {
            calFrom.setTime(employee.getDateStart());
        } else {
            calFrom.setTime(from);
        }
        Calendar calTo = Calendar.getInstance();
        if (employee.getDateEnd() != null && employee.getDateEnd().before(to)) {
            calTo.setTime(employee.getDateEnd());
        } else {
            calTo.setTime(to);
        }
        double fte = employee.getHoursPerDay() * 100 / 8;
        return EmployeeAssignmentHelper.createDTO(employee.getPerson().getName(), employee.getId(), employee
                .getFunction().getDescription(), null, calFrom, calTo, 100, fte, EmployeeAssignmentHelper
                .getAvailabilityStatusFromNoAssignedEmployee(employee), null, " - ", null);
    }

    /**
     * Instancia y devuelve un {@link EmployeeAssignmentDTO} basandose en la
     * informacion del empleado pasada como parametro.
     * 
     * @param employee
     * @return
     */
    public static List<EmployeeAssignmentDTO> createDTO(final Employee employee) {
        return EmployeeAssignmentHelper.createDTO(employee, employee.getFirstDate(), Calendar.getInstance().getTime());
    }

    public static AvailabilityStatus getAvailabilityStatusFromNoAssignedEmployee(final Employee employee) {
        if (employee.esVendible())
            return AvailabilityStatus.NoAsignado;
        else
            return AvailabilityStatus.Area;
    }

    /**
     * Instancia y devuelve un {@link EmployeeAssignmentDTO} basandose en la
     * informacion de la asignacion pasada como parametro
     * 
     * @param employee
     * @return
     */
    public static EmployeeAssignmentDTO createDTO(final EmployeeAssignment assignment) {
        return EmployeeAssignmentHelper.createDTO(assignment.getEmployee().getPerson().getName(), assignment
                .getEmployee().getId(), assignment.getAssignedRole().getDescription(), assignment.getId(), assignment
                .getStartDate(), assignment.getEndDate(), assignment.getAssignmentPorcentage(), assignment.getFTE(),
                assignment.getAvailabilityStatus(), assignment.getProject().getName(), assignment.isTentative() ? "Yes"
                        : "No", null);
    }

    /**
     * Instancia y devuelve un DTO {@link EmployeeAssignmentDTO} en la
     * informacion del empleado pasada como parametro
     * 
     * @param employee
     * @return
     */
    public static EmployeeAssignmentDTO createDTO(final String name, final Long idEmployee, final String role,
            final Long assigId, final Calendar from, final Calendar to, final double porc, final double FTE,
            final AvailabilityStatus status, final String projectName, final String tentative, final String description) {

        EmployeeAssignmentDTO dto = new EmployeeAssignmentDTO();
        dto.setEmployeeName(name);
        dto.setEmployeeID(idEmployee);
        dto.setAssignmentID(assigId);
        dto.setFrom(from);
        dto.setTo(to);
        dto.setRole(role);
        dto.setPorcentage(porc);
        dto.setFTE(FTE);
        dto.setAvailabilityStatus(status);
        dto.setProjectName(projectName);
        dto.setTentative(tentative);
        dto.setDescription(description);
        return dto;
    }

    public static EmployeeAssignmentDTO createDTO(final TimeOff timeOff) {
        Calendar calFrom = Calendar.getInstance();
        calFrom.setTime(timeOff.getDateFrom());
        Calendar calTo = Calendar.getInstance();
        calTo.setTime(timeOff.getDateTo());
        String description = timeOff.getTimeOffType().toString() + " - " + timeOff.getCurrentStatusType().toString();
        return EmployeeAssignmentHelper.createDTO(timeOff.getEmployee().getPerson().getName(), timeOff.getEmployee()
                .getId(), timeOff.getEmployee().getFunction().getDescription(), null, calFrom, calTo, 0.0, 0.0,
                AvailabilityStatus.TimeOff, "TimeOff", String.valueOf(false), description);
    }
}
